﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace Pvf.Core.Converters
{
    internal sealed class PvfListConverter<TValue> : PvfBinaryConverter<List<TValue>>, IDynamicElementCollectionConverter<TValue>
    {
        private IPvfConverter _valueConverter;

        public override List<TValue> Deserialize(BinaryReader reader, IPvfModule module = null)
        {
            var data = new List<TValue>();
            while (true)
            {
                if (!reader.UnitNextPack(out var key))
                {
                    break;
                }

                if (key == 5)
                {
                    reader.BaseStream.Position += 1;

                    var closedFieldKey = reader.ReadInt32();

                    if (Layout.ClosedKeys.Contains(closedFieldKey))
                    {
                        break;
                    }
                }

                if (_valueConverter is IBinaryPvfConverter<TValue> binaryPvfConverter)
                {
                    var value = binaryPvfConverter.Deserialize(reader, module);

                    data.Add(value);
                }
            }
            return data;
        }

        public Type GetBaseType()
        {
            return typeof(TValue);
        }

        public IDynamicElementEnumConverterData GetSubConverterData(int key)
        {
            if (_valueConverter is IDynamicElementConverter dynamicElementConverter)
            {
                return dynamicElementConverter.GetSubConverterData(key);
            }
            return default;
        }

        protected override void OnInit()
        {
            var valueType = Layout.ObjType.GetGenericArguments()[0];

            var deAttr = Layout.BaseProperty.GetCustomAttribute<PvfDynamicElementAttribute>();

            if (deAttr != null)
            {
                _valueConverter = ConverterStatics.MakeDynamicConverter(Layout.Env, deAttr.EnumType, valueType, deAttr.FallbackImplType);
                if (_valueConverter != null)
                {
                    Layout.Keys.AddRange(_valueConverter.Layout.Keys);
                }
            }
            else
            {
                _valueConverter = PvfObjectBuilder.Build(valueType, Layout.Env);
            }

            if (_valueConverter == null)
            {
                throw new NotSupportedException($"不支持的类型:{valueType.FullName}");
            }
        }

        public ICollection<TValue> CreateEmpty()
        {
            return new List<TValue>();
        }

        public Type GetEnumType()
        {
            if (_valueConverter is IDynamicElementConverter dynamicElementConverter)
            {
                return dynamicElementConverter.GetEnumType();
            }
            return null;
        }

        public void SetEntityKey(ref IDynamicElementEntity entity, IDynamicElementEnumConverterData converterData)
        {
            if (_valueConverter is IDynamicElementConverter dynamicElementConverter)
            {
                dynamicElementConverter.SetEntityKey(ref entity, converterData);
            }
        }
    }
}
